「データ転送ミドルウェア勉強会」レポート #dtm_meetup
こんにちは、虎塚です。
1月27日(火)に「データ転送ミドルウェア勉強会」に参加してきましたのでレポートします。イベントは、SAPジャパンさんで開催されました。
今回のテーマは、まず、当日リリースされたばかりのOSSツールEmbulkの解説、次に、データ転送業界のドンHULFTの紹介、そして、今年リリース予定のfluentd v1について、最後に、HTTP/1とHTTP/2両対応のHTTPサーバH2Oの紹介でした。盛りだくさんですね。
懇親会ではトレジャーデータさんからピザが提供されました。SAPジャパンさん、トレジャーデータさん、ありがとうございます。
「バルクデータロードツール『Embulk』リリース 〜 fluentdの柔軟性と堅牢性をバルクでも」
最初のセッションは、トレジャーデータの古橋貞之さんによるEmbulkの思想やアーキテクチャの紹介でした。当日リリースされたばかりということで、会場の注目度も高かったことでしょう。Q&Aも盛り上がり、熱気にあふれるセッションでした。
Emblulkとは何か
Embulkは、本イベント当日にリリースされた新しいOSSのバルクデータローダ。ファイルやストレージ(RDBMS, NoSQL, Cloud Service)間で、データ転送を簡単に実現できる。
Fluentdのバッチ版と考えるとよい。Fluentdと同じように、プラグインで機能を拡張できる。
データ転送には課題がつきものだ。たとえば、PostgreSQLに10GBのCSVファイルをロードしたい、というケースでは、概ね次のような問題が起きる。
- 投入するデータがCSVのファイルフォーマットに沿っていない
- データをクリーニングする必要がある
- 投入に途中で失敗したのでリトライしたら、データが重複してしまった
- cronに登録して定期的にデータを投入したい
- クリーニングスクリプトはRubyやPythonでさらっと書いてあまりチューニングしていないので遅い
- 1日に1回実行するだけならよいが、過去数年分のデータを入れようとすると大変
まとめると、データのクリーニングやノーマライズが面倒くさい、壊れたレコードをどうハンドリングするか、リトライをどうするか、性能が出ない等の問題がある。
トレジャーデータで起きていた問題
fluentdでトレジャーデータにデータを流し込んで、解析などしている。インフラの管理がいらない、Hadoopの知識なくても分析できることなどが、サービスの強みだ。
しかし、トレジャーデータを少しだけ試してみたいお客さんが、いざデータをインポートしようとすると結構大変だったとのこと。スクリプトを書いたり、過去データを大量にアップロードしたりしなければならない。Fluentdは新しいデータをストリーミングでロードするのにはよいが、データをバッチでロードする場合には向いていない。
解決策としてのEmbulk
- プラグインで新しいデータフォーマットやデータソースに対応
- プラグインとしてパッケージングして再利用
- プラグインのコードをgithubなどで継続的に改善
- 今まではローカルに置いていた
CSV、S3、SequenceFile、HDFS、MySQL、Salesforce.comなどのデータを、Hive、Cassandra、Redis、Elasticsearchに投入する。ファイルに限らず、クラウドサービスにも対応する。
Embulk本体は繋ぎをやる。性能を出すために処理を並列化したり、データをバリデーションしたりする。トランザクション制御を行い、中途半端なデータがインポートされないようにする。
プロダクト名「Embulk」は奥さんが提案。embark(船に荷を載せる)にかけている。
Embulkはどのように動くか
EmbulkはコアがJava,プラグインがJRubyで書かれている。
- bintrayからEmbulkのjarをwgetで取得する
- 設定ファイルを書く
- inとoutのデータを定義する
- すべてを細かく書く必要はない。後で紹介するGuessPluginが動いて、ファイルを少しだけ読み込んでスキーマを判定する。クォート文字、ヘッダ、キャラクタセットなども検出する
- 設定ファイルを指定してpreviewを実行する
- データがどのように読み込まれるかが表示される
- 設定ファイルを微修正して、previewを繰り返す
- これでOKという状態になったら、runを実行する
- -oオプションをつけると、新しい設定ファイルを出力する。次回の実行ではそれを使う
- データ投入をcronに登録して実行するときなどに、どこまでデータを読み込んだかを記録しておくため
コマンドラインツールの使い方
プラグインに役割分担させることで、各々のプラグインをシンプルに保っている。
- アーキテクチャ全体
- InputPlugin: レコードを読む
- OutputPlugin: レコードを書く
- ExecutorPlugin: 処理を実行する
- InputPlugin
- レコードを読み込む部分
- InputPluginはレコードを前提とする。CSVファイルなどを入力とする場合は、FileInputPluginを使う
- Decoder Plugin、Parse Pluginといった、それぞれの役割に特化したプラグインがある
- ExecutorPlugin
- レコードは、Executorに渡される
- 現在は、ローカル1台でスレッドを立てて実行するExecutorPluginのみ
- 将来的には、Hadoop対応のExecutorPluginなどの展開が考えられる
- OutputPlugin
- レコードを投入する部分
- Format Plugin、Encoder Pluginなどの役割特化のプラグインがあり、整形や圧縮を担当する
デモ
プロジェクトにexampleが付属していて、試すことができる。
java -jar embulk.jar example
exampleのguessでは、CSVファイルのヘッダを自動検出する。
java -jar embulk.jar guess sample.yaml -o config.yaml
また、タイムスタンプフォーマットを自動検出する。さらに、「20150127」のような一見すると整数だがじつは日付の文字列をも、タイムスタンプとして自動検出できる。
読み込まれるデータをプレビューする。
java -jar embulk.jar preview config.yaml
次の実行時に利用する設定ファイルnext-config.yamlには、next pathが記述される(予定。現在実装中とのこと)。
java -jar embulk.jar run config.yaml -o next-config.yaml
プラグインの書き方
InputPluginの書き方
trunsactionメソッドとrunメソッドを記述する。trunsactionメソッドで、設定ファイルを読み込む(引数config)。Columnでカラムを取得する。yieldで実行しているところに注目(controll.callと同じ)。
commit_reports = yield(task, columns, threads)
threadsに10を指定すると10並列になる。Embulkがrunメソッドを並列に呼んでくれる。commit_reportとして、10個の配列が返る。
runメソッドで、読み込んだファイルをバッファに入れる。次の実行で使う設定ファイルを出力する場合、現在の設定ファイルにマージして返す。
OutputPluginの書き方
OutputPluginには、transactionメソッドの他に、close、add、finish、abort、commitの5つのメソッドがある。OutputPluginでもInputPluginと同様に、yieldでタスクを登録して、実行後にcommit_reportsが返される。
commit_reports = yield(task)
addメソッドには、読み込んだレコードが渡ってくる(exampleでは、それを標準出力に単にputsしている)。abortメソッドは、エラーが起きた時に呼ばれるので、クリーンアップ処理を書く。
GuessPlugin
たとえば、GzipGuess。ファイルのヘッダを見てgzipで圧縮されていると判断したら、decoderのtypeとしてgzipを返す。
def guess(config, sample_buffer) if sample_buffer[0,2] == GZIP_HEADER return {"decoders" => [{"type" => "gzip"}]} end return {} end
また、GuessCharsetでは、Javaのキャラクタセットを判定するライブラリ(ICU4J)を直接使っている。
def guess(config, sample_buffer) # ICU4J detector = com.ibm.icu.text.CharsetDetector.new detector.setText(sample_buffer.to_java_bytes) best_match = detector.detect if best_match.getConfidence < 50 name = "UTF-8" else name = best_match.getName if name == "ISO-8859-1" # ISO-8859-1 means ASCII which is a subset # of UTF-8 in most of cases due to lack of # sample data set name = "UTF-8" end end return {"parser" => {"charset" => name}} end
これらのプラグインは、ユーザが作成して追加できる。RubyGemsとしてリリースすることもできる。
ロードマップ
- GuessPluginをロードする機能
- Perser, Formatter, Decoder, Encoderは、JRubyのプラグインAPI
- ExecutorPlugin
- embulk runにSSHコマンドを指定すると、タスクごとに並列実行できるようにしたい。将来はスパコンで走らせたりできるかも
- ExecutorPluginとしてMapReduce Pluginを作って、Hadoop上で分散処理したい
- arrayやmapなどの型をサポートする
Embulkへの参加方法
- githubでpull requestを送ったりissueを書く
- ブログを書く: 使ってみた、コード読んでみた、ここがイケてる/イケてない等の感想
- embulkという単語を入れてTweetする
- プラグインを書く
- Windows対応にフィードバックする
- 周辺ツールとのインテグレーション(ETLツール、Fluentd、Hadoop)
現在、nahiさん、mugaさん、古橋さんが開発している。
Q&A
- Q1. JSONだと最初の方を少し読み込むだけではフィールドを固定できないのでは?
- A1. たしかにJSONはスキーマレスなので難しい。InputPlugin側で吸収する必要がある。スキーマフルにしたのは、毎回動作が違うのを避けたいから。Guessの段階でスキーマを固定して、その後何回runしても、同じ動作を保つためにこうなっている。
- Q2. なぜJavaで?
- A2. 性能を出したかったため。実際、パフォーマンスチェックの結果、ディスクI/Oがボトルネックになる程度にはパフォーマンスが出ている。
- Q3. Executorで色々なところで動かせるということですが、今の時点ではどこで動きますか? 今後の発展は?
- A3. 今はLocalExecutorだけ。今後やりたいのはHadoop(MapReduce)。Executorの設定ファイルでキーを指定してソートしたりができるはず。あとは、Hadoop YARNのようなコンテナ管理システムにタスクを投げることもできるのでは。
- Q4. タスクが10個あったらスレッド10個に分けて……という説明があったが、1つのファイルが小さければ、さすがにファイル10個に分けたりはしない?
- A4. しない。というより、どうするかはInputPlugin依存。たとえば、遺伝子データなどに使われるSAMファイルフォーマットは、1ファイルが巨大。並列にパースするなら、検討の必要がある。
- Q5. 投入するファイル10個のうち1個だけ失敗した時はどうするか。成功した9個のファイルを生かすかどうか、などもOutputPlugin依存か?
- A5. Yes. 本体にリジュームの機能はまだないので、プラグインでがんばって書くことになる。
- Q6: Redisのプラグインをためしに書いたが、トランザクショナルに実行するのがRedisの性質的にむずかしい。セッションの発表では、Embulkはトランザクショナルな処理ができるとのことだが、トランザクションをサポートしなければ、Embulkプラグインとして認められない?
- A6. そんなことはない。そこはベストエフォート。Embulkを使ったからといってトランザクショナルになるとは限らない。中途半端にデータがロードされうる。
「世界で利用されるファイル転送ツールHULFT」
次は、セゾン情報システムズ HULFT事業部の庄司吉徳さんによるHULFTの説明でした。HULFTといえば、セキュアなファイル転送ツールとして有名ですが、エンタープライズなシステムで採用されることが多いため、直接触る機会がない人も意外と多いのではないでしょうか。HULFTの歴史の重みと品質を守る取り組みの大切さが伝わってくる発表でした。
MFTとは
HULFTは、MFT(Managed file transfer)というカテゴリの製品にあたる。
FTPやHTTPも、ファイル転送ツールだ。しかし、素のFTPではいろいろと問題があり、企業間でファイルをFTP転送するのはむずかしいことが多い。たとえば、成功や失敗の検知、完全性の保証などは素のFTPではむずかしい。そのあたりをカバーするのがMFTの特徴だ。
エンタープライズで業務としてファイル共有をするには、どうするのが適切か
ファイル共有では、自分と共有相手の両方からファイルを編集できる。企業同士でファイル共有するとなると、編集の履歴を残す必要がある。そうしなければ、何かトラブルがあった時、責任の所在が曖昧になってしまう。
そのため、大抵はファイル転送に落ち着く。そして、素のFTPでファイル転送をすると前述のようにエンタープライズの要求を満たせないので、MFTでなければきびしいということになり、HULFTが利用されるケースが多い。
MFTの必要性
FTPは、多くの課題を解決した上で使用する必要がある。たとえば、MD5のCHECKSUMがファイルとともに置いてあり、ダウンロードする人がファイルの完全性を自分で確認する必要がある。企業間で使う場合、そういったユースケースは受け入れられない。
また、ファイル転送だけで作業が終わりということは通常なく、事前事後の処理がある。他の処理との連携も必要だ。
さらに、ファイルの送信に失敗した時の検知の仕組み(意外とむずかしい)や、転送のエビデンスを必要に応じて提供する。失敗操作がミスなのか悪意によるものなのか、後から追跡できなければならない。
HULFTの紹介
HULFTとは、TCP/IPでのファイル転送をベースにした、業務システム間のデータ連携を実現するミドルウェア製品である。機能はシンプルで、ファイル転送のみ。
- 販売開始から2013年で20周年
- 導入企業8000社
- 販売本数 169,000本
- 全国銀行協会の会員銀行では導入率 100%
- 世界40ヶ国で導入: 製造業が海外進出する時にHULFTも一緒に展開
- 日本ではデファクトスタンダード。世界でも第4位
HLFTの機能
「エンタープライズで求められる機能が、すなわちHULFTの機能」。セキュリティ向上、可用性向上など。
一例として、「メッセージ送信」。ファイルとともに付加的な文字列を送って後続処理をさせたい場合、任意の文字列を「メッセージ」として一緒に送る方法がある。メッセージは、送信先でファイル名として利用したり、DBに投入する際のキーにしたりできる。
HULFTとFTPの違い
FTPとHULFTは、ファイル転送という点では同じだが、何が違うのか。
- FTP
- クライアントがアップロード、ダウンロードする。サーバは何もしない。
- インタラクティブに操作する。
- HULFT
- P2P。各ホストに同じモジュールが入っていて、リクエストを発行する側がクライアントになる。
- 事前設定型。設定した通りにしか動かない。最初の設定は面倒だが、設定履歴を残せること、設定以外の転送ができないおかげで不要な送信ミスを防げることが利点。
HULFTが支持される理由
支持される理由1: Japan Quality
日本の人々は、モノづくりで品質を最も重視する。特に製造業では、「ワンストライクアウト(一度やらかしたらおしまい)」という言葉に象徴されるように、障害を出さないことが非常に重要だ。
- 障害発生率 0.1%
- リリース後3ヶ月障害 0件
- お問い合わせ発生率 9%
- 解決率 91.5%
このような高品質をなぜ達成できたかというと、高い品質目標を設定して取り組んでいるから。
- 重大障害発生ゼロ
- リリース後3ヶ月以内の障害ゼロ
- 問題意識
- ソフトウェアは人間が作る。作った人の体調がその時悪かったから障害が起きた、というのは許されない
- ピーク時には100人以上のメンバーが開発にかかわる。その状況で品質を確保するのは難しい
- 品質はある程度までは上げられるが、そこから先を上げようとすると、莫大なコストがかかる
- ウォーターフォール開発モデルの採用
- 絶対的な品質をあげるにはウォーターフォール
- いろいろな製品を開発しているが、HULFTだけはウォーターフォールを一貫して採用
- 開発よりもテストを重視
- 半分以上がテスト工程
- HULFT 8でのテスト実施数 20万項目: 前バージョンのHULFT 7に比べて約2倍になった
支持される理由2: シンプル イズ ベスト
HULFTの機能はファイル転送だけで、中核機能の範囲外にまで機能を拡張することはない。
機能を絞ることは、一見ラクそうだが、バージョンアップ時に機能を追加しないのは勇気が要る。しかし、お客さんが求めているのはこれだけなので、あくまでファイル転送基盤であることにこだわる。
- HULFTラウンドテーブル
- 主要パートナーと製品企画内容を対面でシェア
- EILとかETLとか余計なことせずにファイル転送だけやってほしいといわれた
結果として、ファイル転送の中核機能を大幅に強化する方針をとった。
- パフォーマンス向上:圧縮率上げる、自動最適化
- セキュリティ向上:OS権限設定の利用など
Q&A
- Q1. お客様はファイル共有でプロキシを使うのは避けたがるもの?
- A1. そもそもほとんどの場合は専用線でファイル共有する。また、今回は紹介を省略したが、HULFTには専用のプロキシサーバ製品もある。
- Q2. 開発プロセスはウォーターフォールとのことですが、これまでの試行錯誤などあれば教えてください
- A2. HULFTは一環してウォーターフォール。ウォーターフォールで開発すると時間がかかるので、他の製品ではスパイラルやアジャイルを採用したこともある。しかし、品質がHULFTと全然違う。急いでリリースしなければいけない製品もあるので、ウォーターフォールだけが最適とはもちろん思わないが、HULFTではウォーターフォール以外の選択肢はない。
- Q3. HULFTでは、転送したファイルの世代管理も担保している?
- A3. 世代管理したいお客様としたくないお客様がいる。したいお客様は、設定でできるようになっている。
- Q4. 世代管理ということは同じファイルを作るということだと思うが、スケジュールしてやるの?
- A4. 連番を付与して、違うファイル名で受信する。
- Q5. (Q4に関連して)スケジュールして実行する時も連番?
- A5. HULFTは、送ってから受け取るまでを管理する製品。送信時に名前を連番で管理したい場合、お客さん側でやってもらう
「Fluentd 2015 - v1に向けて -」
3番目のセッションは、トレジャーデータの中川真宏さんから、Fluentdの最近のバージョンのお話でした。「Fluentdを使っている人?」との声に、会場の9割以上の人が手を挙げていました。
なお、今回の発表内容はfluentdのwikiにも書かれているそうです。
Fluentdとは
- Embulkとコンセプト自体は似ている。対象とするデータがストリーミングかバッチかの違い。
- プラグインで機能を拡張できる List of Plugins By Category | Fluentd
- messagepackをベースにしてデータのやりとりをする
バッチでは、処理は失敗か成功かしかない。送り込むデータが大きいと、レイテンシが大きくなる。データを速く解析したいケースや、リアルタイムに速報値が欲しいケースにはツラい。
Fluentdでは、処理するデータが小さい(マイクロバッチと呼んでいる)。転送に失敗したら、ローカルに書き出したり、別のDBに書き出したりできる。
コア
タグベースのメッセージルーティング プラグイン: inputとoutputのプラグインがあるのはEmbulkと同様
アーキテクチャ v0.12
- Input, Output、Filter、Buffer部分がプラグイン
- v0.12からFilterが導入された
- 用途に応じて、FluentdとEmbulkを使い分けよう
- InputとOutputがこんがらがっていた(M*N)のを、プラグインによってM+Nで終わらせよう
v0.10 (old stable)
ログ転送に注力したバージョン。この時にはFilterはまだなかった。
アドホックなプラグインがいくつも出てきたことや、バッチを跨げば跨ぐほどデータをロストする可能性が増えることが問題になっていた。また、複雑なことをしようとすると、設定ファイルが巨大化し、汚くなった。
v0.11(dead version)
※このバージョンはなかったことになったそうです。
v0.12 (current stable)
- イベントハンドリングの改善
- Filter: 以前はタグのマッチごとに処理が切れる欠点があったが、マッチを跨ぐ必要なくinput側までエラーが返るようになった
- Label: タグの書き換えをせずにルーティングできるようになった(内部的にもタグのルーティングまわりを書き換えた)
- At-least-onceセマンティクスをサポートした
- require_ack_response パラメータで設定できる
- 参照: Fluentd v0.12のAt-least-once Semanticsを試す - Tech Notes
- これまでは、かならず届くことを保証していなかった
(tdを使っているなら待つ必要があるが)現在Fluentdを使っている場合、手元でテストして問題なければ、v0.12に移行しても大丈夫とのこと。
v0.14 (next stable)
- プラグインAPIの刷新
- 新しい方を使うとより効率的に書ける(互換性は維持)
- Actorの導入: cool.io以外のイベント駆動IOライブラリも使えるようになるはず
- 新しいベースクラス([WIP] Idea notes for next generation Buffer/Input/Output plugins · Issue #309 · fluent/fluentd)
- サーバーエンジンベースのエンジン
- ロバストな監視デーモンが書ける?
- sub-second time support(#461)
- Googleの人がナノセカンドが欲しいというが、どこで使うのかw
- ダウンタイムなしの再起動
- 運用向け機能強化
- TCP Socketを隣のワーカーに渡して処理を継続
v1 (future stable)
機能はあまり変わらない予定。ほぼ互換性が維持される。
その他の話題
- Windowsサポート
- 参考: Windowsでfluentdを動かす - Qiita
- JRuby support
- 参考: Support JRuby · Issue #317 · fluent/fluentd
- Treasure Agent (td-agent)
- 2がすでに出ていてcurrent stableなので使ってください
- Go版のエージェントを開発中(Windowsで動きます)
- fluentd-ui
- 万葉さんと開発されているFluentdのUI
「H2O - HTTPを、より便利に、より速く」
最後のセッションは、ディー・エヌ・エーの奥一穂さんによる、お仕事で開発されているHTTPサーバH2Oの紹介でした。開発背景や意図から、H2Oが現在備えている機能まで説明されました。
Webアプリ実行環境の変遷
- CGI時代
- Apache + mod_XX時代
- 2009年くらいからのリバースプロキシ流行
- Jetty、Unicorn、Plack
- 粗結合化によって、Apache http serverのレガシー化に引っ張られないようにした
- クラウド化
- アプリケーションやサーバの自動追加削除
- Infrastructure as Code
- TLS必須の流れ
- ウェブブラウザがHTTPを安全でないと警告する動き
- HTTP/2
- 優先度の制御による表示高速化
- ヘッダサイズの削減
Webの普及とともにHTTPの適用範囲は広がり、品質が向上し、皆が使うことでノウハウが共有されて運用がラクになった。
しかし、最近は非ウェブの世界も広がってきた。スマートフォンアプリケーション、IoTなど。これらの場面でマイナープロトコルを使うことで、コストが増える。
直面している課題
- 最適化されたリバースプロキシの決定打がない
- TLSの適切な設定の知識が共有されていない
- HTTP/2対応
H2Oとは
H2Oは、2014年12月にリリースされたばかりのWebサーバ。もとは社内用に開発されたゲームサーバだった。
高品質かつ便利なHTTPサーバを投入することで、HTTPサーバ間の競争を活発にし、HTTPがもっと使われるようになることを意図している。
H2OのnightlyビルドでHTTP/2にすでに対応している。
速い
H2Oは、Nginxより50%から200%ほど速い。これはHTTPパーサが速いため。node.jsのパーサより速い。
H2Oは速いと宣伝することで、対抗コミュニティで改善の動きが見られる(例: io.js)のが素晴らしいので、あえて速いと触れ回っている。
高評価
世界的にも「Apacheの次はH2Oだ」といわれたり、githubのスター数がFluentdに迫っていたりと、リリースしたばかりなのに評価が高い。
- HTTP/1、HTTP/2
- リバースプロキシ: keep-alive、実行中の再構成
- YAMLによる設定
- SSL(自動OCSP stapling)
まとめ
- H2Oは、クラウド化やHTTP/2に対応した、常時TLS時代のHTTPサーバ
- 皆でHTTPの質を上げよう
- H2Oは生まれたてだけど注目度が高いので使ってね
感想
Embulkは、やはり期待通り面白かったです。Embulkを使うだけでトランザクショナルな処理ができたり、リトライ時のデータ重複が処理されたりするわけではなく、プラグイン側で吸収するというのが印象的でした。Embulkはフレームワークなんですね。バッチ処理でデータを投入したい局面は仕事で多々ありそうですので、お世話になるかもしれません。
HULFTのお話も非常に興味深かったです。「HULFTの機能はファイル転送のみ」とおっしゃっていましたが、エンタープライズな世界の外から見ると、そんなこともできるのかと驚く機能を持っているのがHULFTだと思いました。たとえば、HULFT 8で入ったとされていた自動最適化について、機能のより詳しい話を知りたいです。
Fluentdの最近のバージョンの具体的な話はまったく追えていなかったので、参考になりました。また、すでにプラグインが200個もあるというお話に驚きました。Embulkという姉妹プロダクトが公開されたことで、用途に合った場面でますます使われていくのだろうと感じました。
H2Oは、まずプロジェクトの存在自体が素晴らしいと思いました。世の中にHTTPサーバは種類がたくさんあった方が、世界が盛り上がってより良くなるだろうと思いますが、とはいえ本当にHTTPサーバを作る人・会社が(地理的に近くに)いることに感動しました。
あっという間の2時間でした。貴重なお話をありがとうございました。
それでは、また。